const onRE = /^on[^a-z]/
const isOn = key => onRE.test(key)

const options = {
  createElement(tag) { 
    return document.createElement(tag)
  },
  setElementText(el, text) {
    el.textContent = text
  },
  insert(el, parent, anchor = null) { 
    parent.insertBefore(el, anchor)
  },
  patchProps(el, key, prevValue, nextValue) {
    if (isOn(key)) { 
      const eventName = key.slice(2).toLowerCase()
      el.addEventListener(eventName, nextValue)
    }
    else if (key === 'class') { 
      el.className = nextValue || ""
    }
    else if (shouldSetAsProps(el, key, nextValue)) {
      const type = typeof el[key]
      
      if (type === 'boolean' && nextValue === '') {
        el[key] = true
      }
      else { 
        el[key] = nextValue
      }
    }
    else { 
      el.setAttribute(key, nextValue)
    }
  }
}

function shouldSetAsProps(el, key, value) { 
  if (key === 'form' && el.tagName === 'INPUT') { 
    return false;
  }
  
  return key in el;
}

// container.innerHTML = "" 清空内容，会存在一些问题
// 在卸载的时候，可能会调用一些其他钩子函数，比如beforeUnmount等生命周期钩子函数
// 组件上可能会存在自定义指令，卸载的时候我们需要正确的去执行这些指令钩子函数
// container.innerHTML = "" 清空内容,不会自动的清空DOM元素上绑定的事件处理函数

// 最好我们通过dom方式给清除掉，而且应该有具体的处理函数

function createRenderer(options) { 

  const { 
    createElement,
    setElementText,
    insert,
    patchProps
  } = options

  function unmount(vnode) { 
    const parent = vnode.el.parentNode;
    if (parent) { 
      parent.removeChild(vnode.el)
    }
  }

  function render(vnode, container) { 
    if (vnode) {
      patch(container._vnode, vnode, container)
    }
    else { 
      if (container._vnode) { 
        unmount(container._vnode)
      }
    }

    container._vnode = vnode;
    
  }

  function patch(oldVnode, newVnode, container) {
    // 如果旧节点的type和新节点的type不一样，直接卸载旧节点，挂载新节点
    if (oldVnode && oldVnode.type !== newVnode.type) { 
      unmount(oldVnode)
      oldVnode = null
    }

    const { type } = newVnode

    if (typeof type === 'string') {
      // 如果旧节点不存在，就意味着是挂载，调用mountElement函数完成挂载
      if (!oldVnode) {
        mountElement(newVnode, container)
      }
      else {
        // 如果oldVnode存在，就是更新, 暂时省略...
      }
    }
    else if (typeof type === 'object') {
      // todo: 组件处理
      console.log("组件处理")
    }
    else { 
      // todo: 未知类型
      console.log("未知类型")
    }

    
  }

  function mountElement(vnode, container) { 
    // 创建元素
    const el = vnode.el = createElement(vnode.type)
    if (typeof vnode.children === 'string') {
      // 如果子节点是字符串，说明是文本节点，直接挂载
      setElementText(el, vnode.children)
    }
    else if (Array.isArray(vnode.children)) { 
      vnode.children.forEach(child => { 
        patch(null, child, el)
      }) 
    }

    if (vnode.props) { 
      for (const key in vnode.props) { 
        const value = vnode.props[key]
        patchProps(el, key, null, value)
        
      }
    }

    insert(el, container)
  }

  // 其他可能会用到的函数...
  return {
    render
    //...其他的函数
  }
}



const isString = (val) => { 
  return typeof val === 'string'
}

const isObject = (val) => {
  return val !== null && typeof val === 'object'
}

const isArray = Array.isArray

function normalizeClass(value) { 
  let res = "";

  if (isString(value)) {
    res = value;
  }
  else if (isArray(value)) {
    for (let i = 0; i < value.length; i++) {
      const normalized = normalizeClass(value[i])
      if (normalized) { 
        res += normalized + " "
      }
    }
  }
  else if (isObject(value)) { 
    for (const name in value) { 
      if (value[name]) { 
        res += name + " "
      }
    }

  }


  return res;
}

const vnode = {
  type: "button",
  props: {
    onClick: () => { 
      alert("click")
    }
  },
  children:"click me"
}

const renderer = createRenderer(options);
renderer.render(vnode, document.getElementById('app'))



